package com.hivekion.common.config;

import com.hivekion.common.filter.JwtAuthenticationFilter;
import com.hivekion.common.security.JwtAuthenticationProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) // 启用方法级别的权限认证
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

      @Autowired
      @Qualifier("jwtAuthenticationEntryPoint")
      AuthenticationEntryPoint authenticationEntryPoint;

      @Qualifier("customUserDetailServiceImpl")
      @Autowired
      private UserDetailsService userDetailsService;

      @Autowired
      @Qualifier("restAuthenticationAccessDeniedHandler")
      private AccessDeniedHandler accessDeniedHandler;

      /**
       * 身份认证接口
       *
       * @param auth
       * @throws Exception
       */
      @Override
      public void configure(AuthenticationManagerBuilder auth) throws Exception {
	    auth.authenticationProvider(
		    new JwtAuthenticationProvider(userDetailsService)); // 使用自定义登录身份认证组件
      }

      @Override
      protected void configure(HttpSecurity http) throws Exception {
	    // 禁用 csrf, 由于使用的是JWT，我们这里不需要csrf
	    http.cors()
		    .and()
		    .csrf()
		    .disable()
		    .authorizeRequests()
		    .anyRequest()
		    .authenticated()
		    .and()
		    .exceptionHandling()
		    .accessDeniedHandler(accessDeniedHandler)
		    .and()
		    .exceptionHandling()
		    .authenticationEntryPoint(authenticationEntryPoint); // 其他所有请求需要身份认证
	    http.logout()
		    .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler()); // 退出登录处理器
	    // 开启登录认证流程过滤器
	    // http.addFilterBefore(new JwtLoginFilter(authenticationManager()),
	    // UsernamePasswordAuthenticationFilter.class);
	    // 访问控制时登录状态检查过滤器
	    http.addFilterBefore(
		    new JwtAuthenticationFilter(authenticationManager()),
		    UsernamePasswordAuthenticationFilter.class);
	    //        http.addFilterBefore(jwtAuthenticationFilter,
	    // UsernamePasswordAuthenticationFilter.class);

      }

      @Bean
      @Override
      public AuthenticationManager authenticationManager() throws Exception {
	    return super.authenticationManager();
      }

      @Override
      public void configure(WebSecurity web) throws Exception {
	    // 所需要用到的静态资源，允许访问
	    web.ignoring()
		    .antMatchers(
			    "/auth/logout",
			    "/login",
			    "/validateCode",
			    "/wxlogin",
			    "/system/setting/getLoginLogo",
			    "/system/setting/getHomeLogo",
			    "/system/setting/getInfo",
			    "/swagger-ui.html",
			    "/swagger-ui/*",
			    "/swagger-resources/**",
			    "/v2/api-docs",
			    "/v3/api-docs",
			    "/webjars/**");
      }
}
